﻿@page "/"
@using HardHatCore.ApiModels.Shared;
@using HardHatCore.HardHatC2Client.Models;
@using HardHatCore.HardHatC2Client.Services;
@using HardHatCore.HardHatC2Client.Utilities;
@using Microsoft.IdentityModel.Tokens;
@using RestSharp;
@using Blazored.LocalStorage;
@using Microsoft.AspNetCore.SignalR.Client
@using System.IdentityModel.Tokens.Jwt;
@using RestSharp.Authenticators;
@inject IToastService toastService

<div class="row-cols-md-auto">
    <img class="rounded mx-auto d-block" src="Images/MainIcon_Orange_shadows.png" />
    <hr>
</div>
<br>
<br>
 <MudContainer MaxWidth="MaxWidth.Medium">
    <MudPaper Height="300px" Width="100%" Square="true" Class="pa-4">
        <MudTabs @ref="tabs" Elevation="0" Rounded="true" PanelClass="pa-6" Centered="true" Color="@Color.Primary">
            <MudTabPanel Text="Login">
                <MudForm @ref="form" @bind-IsValid="@success" @bind-Errors="@errors">
                    <MudTextField Variant="Variant.Outlined" T="string" @bind-Value="UserName" Label="Username" Required="true" RequiredError="User name is required!" />
                    <MudTextField Variant="Variant.Outlined" T="string" @bind-Value="Password" Label="Password" HelperText="Choose a strong password" @ref="pwField1" InputType="InputType.Password" Required="true" RequiredError="Password is required!" />
                    <div class="d-flex align-center justify-space-between">
                        <MudButton DisableElevation="true" Variant="Variant.Filled" Color="Color.Primary" Disabled="@(!success)" Class="ml-auto" @onclick="@handleValidLogin">Login</MudButton>
                    </div>
                </MudForm>
            </MudTabPanel>
        </MudTabs>
    </MudPaper>
</MudContainer>

@code {
    [Inject]
    public NavigationManager Nav { get; set; }
    [Inject]
    public  ILocalStorageService localStorage { get; set; }
    private static ILocalStorageService _localStorage { get; set; }
    [Inject]
    private RestClient restClient { get; set; }
    public static RestClient _restClient { get; set; }
    private static ToastService _toastService;
    private static NavigationManager _Nav;
    private MudForm form;
    private string UserName { get; set; }
    private string Password { get; set; }
    private bool success;
    private string[] errors;
    private MudTextField<string> pwField1;
    private MudTextField<string> pwField2;
    private MudTabs tabs;
    public static bool IsLoggedIn { get; set; } = false;
    public static string SignedInUser { get; private set; }
    public static HardHatUser? _hhUser { get; private set; }
    public static bool isVisible = false;
    private bool FormSubmitted;

    private string PasswordMatch(string value)
    {
        if (value != pwField1.Value)
            return "Passwords do not match!";
        return null;
    }

    private async Task handleValidLogin()
    {
        try
        {
            isVisible = true;
            FormSubmitted = true;
            StateHasChanged();
            Console.WriteLine("login request started");
            if (HardHatHubClient._hub._hubConnection.State != HubConnectionState.Connected)
            {
                await HardHatHubClient._hub.Connect();
                if (HardHatHubClient._hub._hubConnection.State != HubConnectionState.Connected)
                {
                    ShowErrorToast("HardHat Hub Connection Failed!, please try to login again");
                    return;
                }
            }
            byte[] passwordSalt = await HardHatHubClient._hub.GetUserPasswordSalt(UserName);
            string passwordHash = Hash.HashPassword(Password, passwordSalt);
            LoginRequest loginRequest = new LoginRequest();
            loginRequest.Username = UserName;
            loginRequest.PasswordHash = passwordHash;
            var request = new RestRequest("/login", Method.Post);
            request.AddJsonBody(loginRequest);
            string token = await restClient.PostAsync<string>(request);

            if(token != null)
            {
                //update the restClient service with the new token so other pages have it as well
                RestClientOptions options = new RestClientOptions();
                options.BaseUrl = restClient.Options.BaseUrl;
                options.RemoteCertificateValidationCallback = restClient.Options.RemoteCertificateValidationCallback;
                options.Authenticator = new JwtAuthenticator(token);
                _restClient = new RestClient(options);

                //jwtToken = token;
                await localStorage.SetItemAsync("bearerToken", token);
                await localStorage.SetItemAsync("UserName", UserName);
                //localStorage.SetItemAsync("hasImplantIntRen", false);
                SignedInUser = UserName;
                IsLoggedIn = true;
                _hhUser = await HardHatHubClient._hub.RegisterHardHatUserAfterSignin(SignedInUser);
                StateHasChanged();
                ShowSuccessToast("Logging in!");
                Nav.NavigateTo("/Index");
            }
            else
            {
                isVisible = false;
                StateHasChanged();
                ShowErrorToast("Login Failed!");
            }
        }
        catch (Exception ex)
        {
            UserName = "";
            Password = "";
            isVisible = false;
            StateHasChanged();
            ShowErrorToast($"Login Failed! {ex.Message}");
            Console.WriteLine(ex.Message);
        }

    }

    public static async Task HandleSignOut()
    {
        await _localStorage.RemoveItemAsync("bearerToken");
        await _localStorage.RemoveItemAsync("UserName");
        SignedInUser = "";
        _hhUser = null;
        IsLoggedIn = false;
        Task.Delay(1000).Wait();
        _Nav.NavigateTo(_Nav.BaseUri);
    }



    public static void ShowSuccessToast(string successMessage)
    {
        _toastService.ShowSuccess(successMessage);
    }
    public static void ShowErrorToast(string errorMessage)
    {
        _toastService.ShowError(errorMessage);
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        try
        {
            if (firstRender)
            {
                string token = await localStorage.GetItemAsync<string>("bearerToken");


                if (token != null)
                {
                    //validate token and check it is not expired
                    bool isStillValid = await HardHatHubClient._hub.CheckJWTExpiration(token);
                    if(!isStillValid)
                    {
                        Console.WriteLine("JWT is expired signing out, please log back in to get a new session");
                        await HandleSignOut();
                        return;
                    }

                    SignedInUser = await localStorage.GetItemAsync<string>("UserName");
                    bool userExistsInDB = await HardHatHubClient._hub.VerifyTokenUsernameExists(SignedInUser);
                    if (userExistsInDB)
                    {
                        await localStorage.SetItemAsync("hasImplantIntRen", false);
                        isVisible = true;
                        IsLoggedIn = true;
                        _hhUser = await HardHatHubClient._hub.RegisterHardHatUserAfterSignin(SignedInUser);
                        //update the restClient service with the new token so other pages have it as well
                        RestClientOptions options = new RestClientOptions();
                        options.BaseUrl = restClient.Options.BaseUrl;
                        options.RemoteCertificateValidationCallback = restClient.Options.RemoteCertificateValidationCallback;
                        options.Authenticator = new JwtAuthenticator(token);
                        _restClient = new RestClient(options);
                        StateHasChanged();
                        ShowSuccessToast("Logging in!");
                        Nav.NavigateTo("/Index");
                    }
                    else
                    {
                        await HandleSignOut();
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }
        
    }

    protected override async Task OnInitializedAsync()
    {
        if (Services.HardHatHubClient._hub == null)
        {
            await Services.HardHatHubClient.CreateHubClient();
        }
        _toastService = (ToastService)toastService;
        _localStorage = localStorage;
        _Nav = Nav;
    }
}
